/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package indexfileprocessor;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import model.FieldList;
import model.TokenList;

/**
 *
 * @author Zakiy Firdaus
 */
public class IndexFileWriter {

    /**
     * Konstruktor untuk IndexFileWriter
     * @param path String dari path file yang ingin ditulis
     * @throws IOException 
     */
    public IndexFileWriter(String path) throws IOException {
        File file = new File(path);
        if (!file.exists()) {
            file.createNewFile();
        }
        try {
            //Open the file for both reading and writing
            this.randfile = new RandomAccessFile(file, "rw");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
    
    /**
     * RandomAccessFile yang digunakan pada kelas ini
     */
    private RandomAccessFile randfile;
    
    /**
     * Fungsi untuk menutup RandomAccessFile randfile yang dibuka oleh konstruktor
     * @throws IOException 
     */
    public void closeRandfile() throws IOException{
        this.randfile.close();
    }
    
    /**
     * Fungsi untuk menuliskan PostingList ke dalam file index
     * @param lpl List<PostingList> yang sudah terurut 
     */
    public void writeToFile(TokenList tl) throws IOException{
        randfile.seek(0);
        String sCurrentLine = randfile.readLine();
        String content="";
        List<FieldList> lfl = tl.sortToken();
        if(sCurrentLine==null){
            for(FieldList fl:lfl){
                content = "@@\n" + fl.getToken() + "\n";
                for(int i=1;i<=5;i++){
                    content += "@"+i+"\n"+fl.getPostingListToString(i);
                }
                insert(content, randfile.getFilePointer());
            }
        } else {
            randfile.seek(0);
            String tokenFile = "";
            long fileposawal = 0;
            long filepos = 0;
            boolean enter = true;
            for(FieldList fl:lfl){
                String token = fl.getToken();
                content = "@@\n" + token + "\n";
                filepos = fileposawal;
                tokenFile = getToken(fileposawal);
                fileposawal = randfile.getFilePointer();
                if(tokenFile!=null){
                    while(token.compareToIgnoreCase(tokenFile) > 0){
                        tokenFile = getToken(filepos);
                        if(tokenFile==null){
                            break;
                        } else if(token.compareToIgnoreCase(tokenFile) <= 0){
                            break;
                        }
                        
                        filepos = randfile.getFilePointer();
                    }
                }
                    
                if(token.equalsIgnoreCase(tokenFile)){
                    content = "";
                    long posisi=randfile.getFilePointer();
                    sCurrentLine = randfile.readLine();
                    for(int i=1;i<=4;i++){
                        String sign = "@"+(i+1);
                        randfile.seek(posisi);
                        if(sCurrentLine!=null){
                            while(!sCurrentLine.equalsIgnoreCase(sign)){
                                posisi = randfile.getFilePointer();
                                sCurrentLine = randfile.readLine();
                                if(sCurrentLine==null){
                                    break;
                                }
                            }
                        }
                            
                        content = fl.getPostingListToString(i);
                        insert(content,posisi);
                    }
                    randfile.seek(posisi);
                    insert(fl.getPostingListToString(5),getWritePosition());
                    
                } else if(tokenFile==null){
                    for(int i=1;i<=5;i++){
                        content += "@"+i+"\n"+fl.getPostingListToString(i);
                    }
                    long posisiwrite = getWritePosition();
                    insert(content, posisiwrite, enter);
                    enter = false;
                } else if(token.compareToIgnoreCase(tokenFile) < 0){
                    for(int i=1;i<=5;i++){
                        content += "@"+i+"\n"+fl.getPostingListToString(i);
                    }
                    randfile.seek(filepos);
                    filepos = getWritePosition();
                    insert(content, filepos);
                    fileposawal = filepos;
                }else {
                    for(int i=1;i<=5;i++){
                        content += "@"+i+"\n"+fl.getPostingListToString(i);
                    }
                    insert(content, filepos);
                    fileposawal = filepos;
                }
                    
                
            }
        }
    }
    
    /**
     * Fungsi untuk mencari token pada file paling dekat setelah pointer pos
     * @param pos pointer dari randomaccesfile
     * @return string token dari file
     * @throws IOException 
     */
    public String getToken(long pos) throws IOException{
        String hasil="";
        boolean found=false;
        randfile.seek(pos);
        String curr=randfile.readLine();
        while(curr!=null&&!found){
            if(curr.equals("@@")){
                hasil=randfile.readLine();
                found = true;
            } else {
                curr=randfile.readLine();
            }
            
        }
        if(!found){
            hasil = null;
        }
        
        return hasil;
    }
    
    /**
     * fungsi untuk mencari posisi untuk ditulisi dalam file
     * @return posisi tulis
     * @throws IOException 
     */
    public long getWritePosition() throws IOException{
        long l = randfile.getFilePointer();
        String curr = randfile.readLine();
        
        if(curr!=null){
            while(!curr.equalsIgnoreCase("@@")){
                l = randfile.getFilePointer();
                curr = randfile.readLine();
                if(curr==null){
                    break;
                }
            }
        }
        return l;
    }

    /**
     * Fungsi untuk menuliskan suatu string ke posisi tertentu dalam file
     * @param content string yang ingin dituliskan
     * @param pos posisi di mana string ingin dituliskan
     */
    public void insert(String content, Long pos) {
        try {
            randfile.seek(pos);
            String s = randfile.readLine();
            String append = "";
            while (s != null) {
                append += s;
                s = randfile.readLine();
                if (s != null) {
                    append += "\n";
                }
            }

            randfile.seek(pos);
            randfile.writeBytes(content);
//            raf.write(0x0A);
            randfile.writeBytes(append);
//            randfile.seek(pos);

        } catch (IOException e) {
            System.out.println("IOException:");
            e.printStackTrace();
        }
    }
    
    /**
     * 
     * Fungsi untuk menuliskan suatu string ke posisi tertentu dalam file
     * @param content string yang ingin dituliskan
     * @param pos posisi di mana string ingin dituliskan
     * @param enter boolean untuk menentukan apakah akan ditambahkan newline dalam content
     */
    public void insert(String content, Long pos, boolean enter) {
        try {
            randfile.seek(pos);
            if(enter){
                content = "\n"+content;
            }
            String s = randfile.readLine();
            String append = "";
            while (s != null) {
                append += s;
                s = randfile.readLine();
                if (s != null) {
                    append += "\n";
                }
            }

            randfile.seek(pos);
            randfile.writeBytes(content);
//            raf.write(0x0A);
            randfile.writeBytes(append);
//            randfile.seek(pos);

        } catch (IOException e) {
            System.out.println("IOException:");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws FileNotFoundException, IOException {
        // TODO code application logic here
        IndexFileWriter ifw = new IndexFileWriter("body");
        
        FieldList flapel = new FieldList("apel");
        FieldList flbebek = new FieldList("bebek");
        FieldList flcat = new FieldList("cat");
        
        ArrayList<Integer> ali = new ArrayList<Integer>();
        ali.add(111);
        ali.add(222);
        ali.add(333);
        
        flapel.addPosition(1, 1, ali);
        flapel.addPosition(2, 1, ali);
        flapel.addPosition(3, 1, ali);
        flapel.addPosition(4, 1, ali);
        flapel.addPosition(5, 1, ali);
        flbebek.addPosition(1, 1, ali);
        flbebek.addPosition(2, 1, ali);
        flbebek.addPosition(3, 1, ali);
        flbebek.addPosition(4, 1, ali);
        flbebek.addPosition(5, 1, ali);
        flcat.addPosition(1, 1, ali);
        flcat.addPosition(2, 1, ali);
        flcat.addPosition(3, 1, ali);
        flcat.addPosition(4, 1, ali);
        flcat.addPosition(5, 1, ali);
        
        TokenList tl = new TokenList();
        tl.addToken_position("apel", 1, 11, ali);
        tl.addToken_position("apel", 2, 12, ali);
        tl.addToken_position("apel", 3, 13, ali);
        tl.addToken_position("apel", 4, 14, ali);
        tl.addToken_position("apel", 5, 15, ali);
        tl.addToken_position("bebek", 1, 21, ali);
        tl.addToken_position("bebek", 2, 22, ali);
        tl.addToken_position("bebek", 3, 23, ali);
        tl.addToken_position("bebek", 4, 24, ali);
        tl.addToken_position("bebek", 5, 25, ali);
        tl.addToken_position("cat", 1, 31, ali);
        tl.addToken_position("cat", 2, 32, ali);
        tl.addToken_position("cat", 3, 33, ali);
        tl.addToken_position("cat", 4, 34, ali);
        tl.addToken_position("cat", 5, 35, ali);
        
        ifw.writeToFile(tl);

        ifw.closeRandfile();

//        ifw.writeToFile(content, path);
    }
}
